/*  +*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+

	   		                      Mau-Mau

    +*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+
    
    Copyright (C) <2010>  <Timo Tomasini>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */


#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

bool comp_kann_ziehen();
void computerzug();
void debug_ablage();
void debug_hand();
void debug_stapel();
void geben();
void initialisierung();
void karte_ablegen_comp();
void karte_ablegen_spieler();
void kartenname (short);
void show_hand_spieler();
void sieg();
bool sonderkarte(short);
bool spieler_kann_ziehen();
void spielerzug();
void stapel_count();
void stapel_erstellen();
bool test_if_right(short);
short user_interaction();
void ziehen (short);

short hand_spieler[31], hand_comp[31], stapel[31], ablage[31];	// Hand der beiden Spieler und Stapel erstellen
short z_spieler, z_comp, stapelhoehe, ablagehoehe, player_or_comp, selected, comp_selected;			// Zähler für Hand der beiden Spieler, Stapelhöhe und Ablage erstellen und auf null setzen
string spielername;
bool dev_mode;


int main()
{
	bool neuesspiel;
	initialisierung();
	do
	{
		srand(time(NULL));	  // Startpunkt des Zufallsgenerators auf Systemzeit einstellen
		z_spieler=0, z_comp=0, stapelhoehe=0, ablagehoehe=0;	// Zähler auf null setzen
		player_or_comp=(rand()%2);
		cout<<endl<<spielername<<", lass uns das Spiel beginnen :)\n\n"<<endl;
		sleep(2);
		system("clear");
		stapel_erstellen();
		geben();
		debug_hand();   // Testausgabe für Handkarten
		debug_stapel(); // Testausgabe für Stapel
		ziehen(0);		// 1. Karte in Ablage aus Stapel nehmen
		debug_stapel(); // Testausgabe nach ziehen
		debug_ablage();
		do
		{
			if(player_or_comp==1) // Falls vorher der Computer an der Reihe war (Wird gebraucht für "Wiederholen"-Karte)
			{
				spielerzug();
				debug_hand();
				if(z_spieler==0)
				{
					break;
				}
			}
			if(player_or_comp==0) // Falls vorher Spieler an der Reihe war (Wird gebraucht für "Wiederholen"-Karte)
			{
				computerzug();
				debug_hand();
			}
		} while (z_comp!=0 && z_spieler!=0);

		sieg();
		
		bool restartgame=true;
		do
		{
			char answer;
			cout<<"Möchten Sie ein neues Spiel starten? ([J]a | [N]ein)"<<endl;
			cin>>answer;
			switch (answer)
			{
				case 'J':
				case 'j':
				case 'Y':
				case 'y':
					  neuesspiel=true;
					  restartgame=false;
					  break;
				case 'N':
				case 'n':
					  neuesspiel=false;
					  restartgame=false;
					  break;
				default:
					  cout<<"Falsche Eingabe!"<<endl;
					  break;			  
			}
		} while (restartgame);
		
	} while (neuesspiel);
	return 0;
}


void kartenname (short nr) // Kartennamen zuweisen
{
	switch(nr)
	{
		case 0:
			cout<<"Schwarz - 7 (2 nehmen)";
			break;
		case 1:
			cout<<"Schwarz - 8 (wiederholen)";
			break;
		case 2:
			cout<<"Schwarz - 9";
			break;
		case 3:
			cout<<"Schwarz - 10";
			break;
		case 4:
			cout<<"Schwarz - Bube";
			break;
		case 5:
			cout<<"Schwarz - Dame";
			break;
		case 6:
			cout<<"Schwarz - König";
			break;
		case 7:
			cout<<"Schwarz - Ass";
			break;
		case 8:
			cout<<"Grün - 7 (2 nehmen)";
			break;
		case 9:
			cout<<"Grün - 8 (wiederholen)";
			break;
		case 10:
			cout<<"Grün - 9";
			break;
		case 11:
			cout<<"Grün - 10";
			break;
		case 12:
			cout<<"Grün - Bube";
			break;
		case 13:
			cout<<"Grün - Dame";
			break;
		case 14:
			cout<<"Grün - König";
			break;
		case 15:
			cout<<"Grün - Ass";
			break;
		case 16:
			cout<<"Rot - 7 (2 nehmen)";
			break;
		case 17:
			cout<<"Rot - 8 (wiederholen)";
			break;
		case 18:
			cout<<"Rot - 9";
			break;
		case 19:
			cout<<"Rot - 10";
			break;
		case 20:
			cout<<"Rot - Bube";
			break;
		case 21:
			cout<<"Rot - Dame";
			break;
		case 22:
			cout<<"Rot - König";
			break;
		case 23:
			cout<<"Rot - Ass";
			break;
		case 24:
			cout<<"Orange - 7 (2 nehmen)";
			break;
		case 25:
			cout<<"Orange - 8 (wiederholen)";
			break;
		case 26:
			cout<<"Orange - 9";
			break;
		case 27:
			cout<<"Orange - 10";
			break;
		case 28:
			cout<<"Orange - Bube";
			break;
		case 29:
			cout<<"Orange - Dame";
			break;
		case 30:
			cout<<"Orange - König";
			break;
		case 31:
			cout<<"Orange - Ass";
			break;
		default:
			cout<<"Fehler!";
	}
}

void initialisierung()
{
	system("clear");
	cout<<"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+\n\n  Mau-Mau :) - (c) Timo Tomasini\n\t\t(2010)\n+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+\n"<<endl;
	cout<<"Wie heißen Sie? (Eingaben bitte mit Enter bestätigen)"<<endl;
	cin>>spielername;
	if(spielername == "devdeb")
	{
		dev_mode=true;
	}
	else
	{
		dev_mode=false;
	}
}

void stapel_erstellen()
{
	for(short i=0; i<32; ++i)   // Stapel mit Karten füllen
	{
		stapel[i]=i;
		++stapelhoehe;
	}
}

void geben()
{
	for(short i=0; i<6; ++i)
	{
		short kartenpunkt=rand()%(stapelhoehe);		// Menschen 6 Karten geben
		hand_spieler[i]=stapel[kartenpunkt];
		for(short z=kartenpunkt; z<(stapelhoehe-1); ++z)
		{
			stapel[z]=stapel[z+1];
		}
		++z_spieler;
		--stapelhoehe;
		kartenpunkt=rand()%(stapelhoehe);		// Computer 6 Karten geben
		hand_comp[i]=stapel[kartenpunkt];
		for(short z=kartenpunkt; z<(stapelhoehe-1); ++z)
		{
			stapel[z]=stapel[z+1];
		}
		++z_comp;
		--stapelhoehe;
	}
}

void ziehen (short ziel) // Karte Ziehen
{
	short kartenpunkt=rand()%(stapelhoehe);
	switch(ziel)
	{
		case 0:			// Falls Ziel: Ablage --> ziel==0
			ablage[ablagehoehe]=stapel[kartenpunkt];
			++ablagehoehe;
			break;
		case 1:			// Falls Ziel: Spielerhand --> ziel==1
			hand_spieler[z_spieler]=stapel[kartenpunkt];
			++z_spieler;
			break;
		case 2:			// Falls Ziel: Computerhand --> ziel==2
			hand_comp[z_comp]=stapel[kartenpunkt];
			++z_comp;
			break;
		default:
			cout<<"Fehler!"<<endl;
	}
	if (kartenpunkt<(stapelhoehe-1))
	{
		for(short i=kartenpunkt; i<(stapelhoehe-1); ++i)
		{
			stapel[i]=stapel[i+1];
		}
		
	}
	--stapelhoehe;
	stapel_count();
}

void show_hand_spieler()
{

	// cout<<"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+\n\n\t  Mau-Mau :)\n\n+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+\n"<<endl;
	cout<<spielername<<", Sie sind nun am Zug!\n\nEs liegt # ";
	kartenname(ablage[ablagehoehe-1]);
	cout<<"\n\nDer Computer hat "<<z_comp<<" Karten auf der Hand.\n\n*******"<<endl;
	for(short i=0; i<z_spieler; ++i)
	{
		cout<<"\n"<<i+1<<") # ";
		kartenname(hand_spieler[i]);
		cout<<endl;
	}
	cout<<endl;
}

short user_interaction()
{
	do
	{
		short auswahl=0;
		cout<<"Welche Karte möchten Sie legen?"<<endl;
		cin>>auswahl;
		cin.clear();
		cin.ignore();
		if(auswahl>=1 && auswahl<=z_spieler)
		{
			return auswahl;
			break;
		}
		else
		{
			cout<<"Falsche Eingabe!"<<endl;
		}
	} while (true);		
}

bool test_if_right(short karte)
{
	if(karte%8 == ablage[ablagehoehe-1]%8 || karte/8 == ablage[ablagehoehe-1]/8)
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool spieler_kann_ziehen() // Überprüfen ob Spieler min 1 gültige Karte auf der Hand hat
{
	for(short i=0; i<z_spieler; ++i)
	{
		if(test_if_right(hand_spieler[i]))
		{
			return true;
		}
	}
	return false;
}

bool comp_kann_ziehen()
{
	for(short i=0; i<z_comp; ++i)
	{
		if(test_if_right(hand_comp[i]))
		{
			return true;
		}
	}
	return false;
}

void sieg()
{
	if(z_spieler==0)
	{	
		system("clear");
		cout<<"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+\n\nHerzlichen Glückwunsch, Sie haben gewonnen! ;D\n\n+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+\n\n"<<endl;
	}
	else
	{
		system("clear");
		cout<<"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+\n\nLeider hat der Computer gewonnen... ;_;\n\n+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+\n\n"<<endl;
	}
}

void spielerzug()
{
	player_or_comp=0;
	if(spieler_kann_ziehen())
	{
		show_hand_spieler();
		selected=user_interaction();
		system("clear");
		if(test_if_right(hand_spieler[selected-1])) // Falls die gewählte Karte gültig ist, lege gewünschte Karte auf Ablage
		{
			if(sonderkarte(hand_spieler[selected-1]))
			{
				player_or_comp=1; // Es wird so getan als wäre nach diesem Zug der Computer an der Reihe gewesen.
			}
			karte_ablegen_spieler();
		}
		else
		{
			cout<<"Karte nicht möglich!\n"<<endl;
			player_or_comp=1;
		}
	}
	else
	{
		ziehen(1);
		cout<<"Sie mussten eine Karte ziehen!\n"<<endl;
	}
}

void computerzug()
{
	cout<<"Der Computer ist am Zug...\n"<<endl;
	sleep(1);
	player_or_comp=1;
	if(comp_kann_ziehen())
	{
		for(short i=0; i<z_comp; ++i)
		{
			if(test_if_right(hand_comp[i]))
			{
				comp_selected=i;
				break;
			}
		}
		if(sonderkarte(hand_comp[comp_selected]))
		{
			player_or_comp=0; // Es wird so getan als wäre nach diesem Zug der Spieler an der Reihe gewesen.
		}
		karte_ablegen_comp();
	}
	else
	{
		ziehen(2);
		cout<<"Der Computer musste eine Karte ziehen...\n"<<endl;
	}
}

bool sonderkarte(short karte)
{
	if(karte%8==0)
	{
		cout<<"\"2 Nehmen\" wurde gelegt!\n"<<endl;
		if(player_or_comp==1)
		{
			ziehen(1);
			ziehen(1);
			cout<<"Sie mussten 2 Karten ziehen!\n"<<endl;
		}
		else
		{
			ziehen(2);
			ziehen(2);
			cout<<"Der Computer musste 2 Karten ziehen!\n"<<endl;
		}
	}
	if(karte%8==1)
	{
		cout<<"\"Wiederholen\" wurde gelegt!\n"<<endl;
		return true;	// Wiederholen wurde gelegt
	}
	return false; // Wiederholen wurde nicht gelegt
}
	
void stapel_count()
{
	if(stapelhoehe==0)
	{
		for(short i=0; i<(ablagehoehe-1); ++i)
		{
			stapel[i]=ablage[i];
		}
		stapelhoehe=ablagehoehe;
		ablagehoehe=0;
		ziehen(0);
		cout<<"Stapel leer. Neuer Stapel wird gemischt...\n"<<endl;
		sleep(1);
	}
}

void karte_ablegen_spieler()
{
	ablage[ablagehoehe]=hand_spieler[selected-1];
	for(short i=(selected-1); i<(z_spieler-1); ++i)
	{
		hand_spieler[i]=hand_spieler[i+1];
	}
	++ablagehoehe;
	--z_spieler;
}

void karte_ablegen_comp()
{
	ablage[ablagehoehe]=hand_comp[comp_selected];
	for(short i=(comp_selected); i<(z_comp-1); ++i)
	{
		hand_comp[i]=hand_comp[i+1];
	}
	++ablagehoehe;
	--z_comp;
}

void debug_hand()   // Debuginfos für Hand ausgeben
{
	if(dev_mode)
	{
		cout<<"Karten der Spieler ausgeben...\n\nSpieler:"<<endl;
		for(short i=0; i<z_spieler; ++i)
		{
			cout<<hand_spieler[i]<<endl;
		}
		cout<<"\nComp:"<<endl;
		for(short i=0; i<z_comp; ++i)
		{
			cout<<hand_comp[i]<<endl;
		}
		cout<<"\n"<<endl;
	}
}

void debug_stapel()   // Debuginfos für Stapel ausgeben
{
	if(dev_mode == true)
	{
		cout<<"\nStapel:"<<endl;
		for(short i=0; i<stapelhoehe; ++i)
		{
			cout<<stapel[i]<<endl;
		}
		cout<<"Stapelhöhe: "<<stapelhoehe<<endl;
	}
}

void debug_ablage()   // Debuginfos für Ablage ausgeben
{
	if(dev_mode == true)
	{
		cout<<"Ablage:"<<endl;
		for(short i=0; i<ablagehoehe; ++i)
		{
			cout<<ablage[i]<<endl;
		}
		cout<<"Ablagehöhe: "<<ablagehoehe<<endl;
	}
}